package com.lsu.proxy.experiment;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 我的代理对象
 *
 * @Author wang suo
 * @Date 2020/12/31 0031 9:18
 * @Version 1.0
 */
public class MyInvocation implements InvocationHandler {

    private static List<String> aopMethods = new ArrayList<>();
    private static String aopBeanName = "";
    private static String originalClass = "";
    private static Object aopBean = null;
    private static Object oriBean = null;

    /*
     * 通过静态代码块初始化全局变量
     */
    static {
        getConfigFromXml();
        try {
            // AOP 对象
            aopBean = Class.forName(aopBeanName).newInstance();
            // 原始对象
            oriBean = Class.forName(originalClass).newInstance();
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        List<Method> methods = methodNameToObj();
        // 前置通知
        methods.get(0).invoke(aopBean);

        method.invoke(oriBean, args);

        // 后置通知
        methods.get(1).invoke(aopBean);
        return null;
    }

    /**
     * 将方法名转为方法对象
     *
     * @return 返回对象列表
     */
    private static List<Method> methodNameToObj() {
        List<Method> methods = new ArrayList<>();
        // 通过反射回去所有的方法
        Method[] ms = aopBean.getClass().getMethods();
        // 提取出在配置文件中的方法
        for (Method m : ms) {
            for (String aopMethod : aopMethods) {
                if (aopMethod.equals(m.getName())) {
                    methods.add(m);
                }
            }
        }
        return methods;
    }

    /**
     * 从配置文件中初始化类名与方法名
     */
    private static void getConfigFromXml() {
        SAXReader reader = new SAXReader();
        Document document;
        try {
            document = reader.read(new File("D:\\02文档\\01文档\\大三作业和文件\\设计模式\\代码\\design-patterns\\src\\main\\resources\\config.xml"));
            Element root = document.getRootElement();
            // proxy 节点
            List<Element> allProxy = root.elements();
            // 所有的 proxy 节点
            for (Element proxy : allProxy) {
                Attribute className = proxy.attribute("class");
                originalClass = className.getText();
                List<Element> proxyElements = proxy.elements();

                for (Element proxyElement : proxyElements) {
                    // element 是 method
                    List<Element> methodElements = proxyElement.elements();

                    for (Element methodElement : methodElements) {
                        aopBeanName = methodElement.attribute("bean").getText();
                        aopMethods.add(methodElement.attribute("mtd").getText());
                    }
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}
